package com.soccertgc.core.cards
{
	
	import com.soccertgc.core.Position;
	import com.soccertgc.core.Role;
	import com.soccertgc.core.School;
	import com.soccertgc.core.Stats;
	import com.soccertgc.core.Target;
	import com.soccertgc.core.TargetType;

	public class ActionCard extends ExpCard
	{

		// -------------------------------------------------------------------------------
		// CONSTANTS
		// -------------------------------------------------------------------------------
		
		// JSON properties names
		protected static const 		JSON_PROPERTY_TARGET_POSITIONS:String		= "fieldZone";
		protected static const 		JSON_PROPERTY_BALL_CONDITION:String			= "ballStatus";
		protected static const 		JSON_PROPERTY_TARGET:String					= "target";
		protected static const 		JSON_PROPERTY_INPUT:String					= "input";
		protected static const 		JSON_PROPERTY_INPUT_TARGET:String			= "target";
		protected static const 		JSON_PROPERTY_INPUT_TARGET_TYPE:String		= "type";
		
		
		// Default values
		protected static const		DEFAULT_ROLE:Role							= Role.NONE;
		protected static const		DEFAULT_DURATION:int						= 1;
		protected static const		DEFAULT_COST:int							= 1;
		protected static const		DEFAULT_ACTION_TEXT:String					= "";
		protected static const		DEFAULT_BALL_CONDITION:CardBallCondition	= CardBallCondition.ALWAYS;
		
		// Events
		public static const			EVENT_SCHOOLS_CHANGED:String 				= "schoolsChanged";
		
		// -------------------------------------------------------------------------------
		// FIELDS
		// -------------------------------------------------------------------------------
		
		protected var _role:Role;
		protected var _duration:int;
		protected var _cost:int;
		protected var _actionText:String;
		protected var _stats:Stats;
		protected var _ballCondition:CardBallCondition;
		protected var _target:Target;
		protected var _targetInput:CardTargetInput;
		protected var _targetPositions:Vector.<Position>;
		
		// -------------------------------------------------------------------------------
		// CONSTRUCTORS
		// -------------------------------------------------------------------------------
		
		public function ActionCard()
		{
			// Call ancestor
			super();
			// Init data
			_type = CardType.ACTION;
			// Init objets
			_stats = new Stats();
			_targetPositions = new Vector.<Position>();
			// Clear
			clear();
		}
		
		// -------------------------------------------------------------------------------
		// PROPERTIES
		// -------------------------------------------------------------------------------

		public function get role():Role
		{
			return _role;
		}
		
		public function set role(value:Role):void
		{
			_role = value;
		}
		
		public function get duration():int
		{
			return _duration;
		}

		public function set duration(value:int):void
		{
			_duration = value;
		}

		public function get cost():int
		{
			return _cost;
		}

		public function set cost(value:int):void
		{
			_cost = value;
		}

		public function get actionText():String
		{
			return _actionText;
		}

		public function set actionText(value:String):void
		{
			_actionText = value;
		}
		
		public function get targetPositions():Vector.<Position>
		{
			return _targetPositions;
		}
		
		public function set targetPositions(value:Vector.<Position>):void
		{
			_targetPositions = value;
		}
		
		public function get ballCondition():CardBallCondition
		{
			return _ballCondition;
		}
		
		public function set ballCondition(value:CardBallCondition):void
		{
			_ballCondition = value;
		}
		
		public function get target():Target
		{
			return _target;
		}
		
		public function set target(value:Target):void
		{
			_target = value;
		}
		
		public function get targetInput():CardTargetInput
		{
			return _targetInput;
		}
		
		public function set targetInput(value:CardTargetInput):void
		{
			_targetInput = value;
		}
		
		public function get hasTargetInput():Boolean
		{
			return _targetInput != null && _targetInput != CardTargetInput.NONE; 
		}
		
		public function get stats():Stats
		{
			return _stats;
		}
		
		public function set stats(value:Stats):void
		{
			_stats = value;
		}
		
		// -------------------------------------------------------------------------------
		// PRIVATE METHODS
		// -------------------------------------------------------------------------------
		
		// DATA OBJECT IMPLEMENTATION
			
		override protected function validate(data:Object):void
		{
			// Call ancestor
			super.validate(data);
			// Validating data
			if (!data.hasOwnProperty(JSON_PROPERTY_ROLE)) 		throwLoadMissingPropError("role");
			if (!data.hasOwnProperty(JSON_PROPERTY_SCHOOL)) 	throwLoadMissingPropError("school");
			if (!data.hasOwnProperty(JSON_PROPERTY_ACTIONTEXT)) throwLoadMissingPropError("action text");
			if (!data.hasOwnProperty(JSON_PROPERTY_DURATION)) 	throwLoadMissingPropError("duration");
			if (!data.hasOwnProperty(JSON_PROPERTY_COST)) 		throwLoadMissingPropError("cost");
		}
			
		override protected function fill(data:Object):void
		{
			// Call ancestor
			super.fill(data);
			// Load data
			_role 		= Role.getBySign(data[JSON_PROPERTY_ROLE]);
			_actionText = data[JSON_PROPERTY_ACTIONTEXT];
			_cost 		= int(data[JSON_PROPERTY_COST]);
			_duration 	= int(data[JSON_PROPERTY_DURATION]);
			// Check if the data contains a single school or a list of schools
			if (data[JSON_PROPERTY_SCHOOL] is Array)
			{
				// Retrieve the school list
				var rawSchools:Array = data[JSON_PROPERTY_SCHOOL] as Array;
				// Adds all the schools to the card
				for (var i:int=0; i<rawSchools.length; i++)
				{
					var school:School = School.getById(rawSchools[i]);
					addSchool(school);
				}
			}
			else
			{
				// Adds a single school to the card (old getCollection.php implementation)
				addSchool(School.getById(data[JSON_PROPERTY_SCHOOL]));
			}
			// Loads stats
			_stats = new Stats();
			_stats.load(data);
			
			// ADVANCED PARSING
			
			// Ball condition
			if (data.hasOwnProperty(JSON_PROPERTY_BALL_CONDITION))
			{
				_ballCondition = CardBallCondition.getById(uint(data[JSON_PROPERTY_BALL_CONDITION]));
			}
			// Target
			if (data.hasOwnProperty(JSON_PROPERTY_TARGET))
			{
				_target = Target.getByDescription(data[JSON_PROPERTY_TARGET]);
			}
			// Target input
			if (data.hasOwnProperty(JSON_PROPERTY_INPUT))
			{
				// Retrieve the raw input
				var rawInput:Object = data[JSON_PROPERTY_INPUT];
				// Check if the input object exists
				if (!(rawInput is String))
				{
					// Retrieve the raw target input
					var rawTargetInputTarget:Object = rawInput[JSON_PROPERTY_INPUT][JSON_PROPERTY_INPUT_TARGET];
					// Retrieve the raw input type
					var rawTargetInputType:String = rawTargetInputTarget[JSON_PROPERTY_INPUT_TARGET_TYPE];
					// retrieve the input type
					var targetInputType:TargetType = TargetType.getByDescription(rawTargetInputType);
					// Create the target input
					_targetInput = CardTargetInputFactory.create(targetInputType, rawTargetInputTarget);
				}
				else
				{
					_targetInput = CardTargetInput.NONE;
				}
			}
			// Target positions
			if (data.hasOwnProperty(JSON_PROPERTY_TARGET_POSITIONS))
			{
				var targetPositions:Vector.<Position> = new Vector.<Position>();
				// Check if the target position is an array
				if (data[JSON_PROPERTY_TARGET_POSITIONS] is Array)
				{
					// Loop over target positions
					var raw_positions:Array = data[JSON_PROPERTY_TARGET_POSITIONS];
					for (var j:int = 0; j < raw_positions.length; j++)
					{
						targetPositions.push(Position.getBySign(raw_positions[j]));
					}
				}
				else
				{
					// Any position
					targetPositions.push(Position.ANY);
				}
				// Clear and populate the target positions
				_targetPositions.splice(0, _targetPositions.length);
				for (var k:int = 0; k < targetPositions.length; k++) _targetPositions.push(targetPositions[k]);
			}
			
		}
		
		// -------------------------------------------------------------------------------
		// PUBLIC METHODS
		// -------------------------------------------------------------------------------
		
		override public function copy(card:Card):void
		{
			super.copy(card);
			// Cast the card
			var action:ActionCard = card as ActionCard;
			// Copy properties
			_role				= action.role;
			_duration			= action.duration;
			_cost				= action.cost;
			_actionText			= action.actionText;
			_stats				= action.stats.clone();
			_target				= action.target;
			_targetPositions	= action.targetPositions; // array di enumeratori posso copiare la reference
			_ballCondition		= action.ballCondition;
		}
		
		override public function clone():Card
		{
			var clone:ActionCard = new ActionCard();
			clone.copy(this);
			return clone;
		}
		
		override public function clear():void
		{
			// Ancestor
			super.clear();
			// Clears data
			_role			= DEFAULT_ROLE;
			_duration		= DEFAULT_DURATION;
			_cost			= DEFAULT_COST;
			_actionText		= DEFAULT_ACTION_TEXT;
			_ballCondition	= DEFAULT_BALL_CONDITION;
			// Clears objects
			_stats.clear();
			_targetPositions.splice(0, _targetPositions.length);
			_targetPositions.push(Position.ANY);
		}

	}
}